package logger

import (
    "bytes"
    "context"
    "encoding/json"
    "errors"
    "fmt"
    "os"
    "path/filepath"
    "strings"
    "testing"
    "time"

    kwerrors "kwdb-import/pkg/errors"
)

// TestParseLogLevel 测试日志级别解析
func TestParseLogLevel(t *testing.T) {
	tests := []struct {
		input    string
		expected LogLevel
		shouldErr bool
	}{
		{"debug", DebugLevel, false},
		{"DEBUG", DebugLevel, false},
		{"info", InfoLevel, false},
		{"INFO", InfoLevel, false},
		{"warn", WarnLevel, false},
		{"WARN", WarnLevel, false},
		{"warning", WarnLevel, false},
		{"WARNING", WarnLevel, false},
		{"error", ErrorLevel, false},
		{"ERROR", ErrorLevel, false},
		{"fatal", FatalLevel, false},
		{"FATAL", FatalLevel, false},
		{"invalid", InfoLevel, true},
		{"", InfoLevel, true},
	}
	
	for _, tt := range tests {
		t.Run(tt.input, func(t *testing.T) {
			level, err := ParseLogLevel(tt.input)
			
			if tt.shouldErr {
				if err == nil {
					t.Errorf("Expected error for input %q, but got none", tt.input)
				}
				return
			}
			
			if err != nil {
				t.Errorf("Unexpected error for input %q: %v", tt.input, err)
				return
			}
			
			if level != tt.expected {
				t.Errorf("Expected level %v for input %q, got %v", tt.expected, tt.input, level)
			}
		})
	}
}

// TestLogLevelString 测试日志级别字符串表示
func TestLogLevelString(t *testing.T) {
	tests := []struct {
		level    LogLevel
		expected string
	}{
		{DebugLevel, "DEBUG"},
		{InfoLevel, "INFO"},
		{WarnLevel, "WARN"},
		{ErrorLevel, "ERROR"},
		{FatalLevel, "FATAL"},
		{LogLevel(999), "UNKNOWN"},
	}
	
	for _, tt := range tests {
		t.Run(tt.expected, func(t *testing.T) {
			result := tt.level.String()
			if result != tt.expected {
				t.Errorf("Expected %q, got %q", tt.expected, result)
			}
		})
	}
}

// TestFieldCreators 测试字段创建函数
func TestFieldCreators(t *testing.T) {
	tests := []struct {
		name     string
		field    Field
		expected interface{}
	}{
		{"String", String("key", "value"), "value"},
		{"Int", Int("key", 42), 42},
		{"Int64", Int64("key", int64(42)), int64(42)},
		{"Float64", Float64("key", 3.14), 3.14},
		{"Bool", Bool("key", true), true},
		{"Duration", Duration("key", time.Second), "1s"},
		{"Time", Time("key", time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)), "2023-01-01T00:00:00Z"},
	}
	
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.field.Key != "key" {
				t.Errorf("Expected key 'key', got %q", tt.field.Key)
			}
			if tt.field.Value != tt.expected {
				t.Errorf("Expected value %v, got %v", tt.expected, tt.field.Value)
			}
		})
	}
}

// TestErrorField 测试错误字段
func TestErrorField(t *testing.T) {
    err := errors.New("test error")
    field := ErrorField(err)
	
	if field.Key != "error" {
		t.Errorf("Expected key 'error', got %q", field.Key)
	}
	if field.Value != "test error" {
		t.Errorf("Expected value 'test error', got %q", field.Value)
	}
}

// TestNewLogger 测试日志记录器创建
func TestNewLogger(t *testing.T) {
	// 测试默认配置
	logger, err := NewLogger(nil)
	if err != nil {
		t.Fatalf("Failed to create logger with default config: %v", err)
	}
	if logger == nil {
		t.Fatal("Logger should not be nil")
	}
	
	// 测试自定义配置
	config := &Config{
		Level:  DebugLevel,
		Format: JSONFormat,
		Output: "stderr",
		Caller: false,
	}
	
	logger, err = NewLogger(config)
	if err != nil {
		t.Fatalf("Failed to create logger with custom config: %v", err)
	}
	
	if logger.GetLevel() != DebugLevel {
		t.Errorf("Expected level %v, got %v", DebugLevel, logger.GetLevel())
	}
}

// TestLoggerWritesSqlFieldWithError 验证错误日志包含sql字段并写入文件
func TestLoggerWritesSqlFieldWithError(t *testing.T) {
    tempDir := t.TempDir()
    logFile := filepath.Join(tempDir, "sql_error.log")

    config := &Config{
        Level:  InfoLevel,
        Format: TextFormat,
        Output: logFile,
        Caller: false,
    }

    logger, err := NewLogger(config)
    if err != nil {
        t.Fatalf("NewLogger failed: %v", err)
    }

    // 写入一条包含sql字段的错误日志
    logger.Error("SQL执行失败", String("sql", "SELECT 1/0;"), ErrorField(fmt.Errorf("division by zero")))

    // 关闭以刷新文件
    _ = logger.Close()

    // 读取文件内容
    content, err := os.ReadFile(logFile)
    if err != nil {
        t.Fatalf("Failed to read log file: %v", err)
    }

    text := string(content)
    if !strings.Contains(text, "SQL执行失败") {
        t.Fatalf("log missing message: %s", text)
    }
    if !strings.Contains(text, "sql=SELECT 1/0;") {
        t.Fatalf("log missing sql field: %s", text)
    }
    if !strings.Contains(text, "error=division by zero") {
        t.Fatalf("log missing error field: %s", text)
    }
}

// TestLoggerWithBuffer 测试带缓冲区的日志记录器
func TestLoggerWithBuffer(t *testing.T) {
	buf := &bytes.Buffer{}
	
	// 创建自定义日志记录器
	logger := &KWDBLogger{
		level:  DebugLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 测试不同级别的日志
	logger.Debug("debug message")
	logger.Info("info message")
	logger.Warn("warn message")
	logger.Error("error message")
	
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	if len(lines) != 4 {
		t.Errorf("Expected 4 log lines, got %d", len(lines))
	}
	
	// 验证日志级别
	expectedLevels := []string{"[DEBUG]", "[INFO]", "[WARN]", "[ERROR]"}
	for i, line := range lines {
		if !strings.Contains(line, expectedLevels[i]) {
			t.Errorf("Line %d should contain %s, got: %s", i, expectedLevels[i], line)
		}
	}
}

// TestLoggerWithFields 测试带字段的日志记录
func TestLoggerWithFields(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 测试单个字段
	logger.Info("test message", String("key1", "value1"), Int("key2", 42))
	
	output := buf.String()
	if !strings.Contains(output, "key1=value1") {
		t.Errorf("Output should contain 'key1=value1', got: %s", output)
	}
	if !strings.Contains(output, "key2=42") {
		t.Errorf("Output should contain 'key2=42', got: %s", output)
	}
}

// TestLoggerWithError 测试错误日志记录
func TestLoggerWithError(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
    // 测试标准错误
    standardErr := errors.New("standard error")
    errorLogger := logger.WithError(standardErr)
    errorLogger.Error("something went wrong")
	
	output := buf.String()
	if !strings.Contains(output, "standard error") {
		t.Errorf("Output should contain error message, got: %s", output)
	}
	
	// 清空缓冲区
	buf.Reset()
	
	// 测试KWDBError
    kwdbErr := kwerrors.NewParseError("syntax error", 10, 5)
    kwdbErr.WithSuggestion("Check your SQL")
    errorLogger = logger.WithError(kwdbErr)
    errorLogger.Error("parse failed")
	
	output = buf.String()
	if !strings.Contains(output, "syntax error") {
		t.Errorf("Output should contain KWDB error message, got: %s", output)
	}
    if !strings.Contains(output, "error_type=PARSE_ERROR") {
        t.Errorf("Output should contain error type, got: %s", output)
    }
    if !strings.Contains(output, "error_suggestion=Check your SQL") {
        t.Errorf("Output should contain error suggestion, got: %s", output)
    }
}

// TestLoggerWithContext 测试上下文日志记录
func TestLoggerWithContext(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 创建带追踪信息的上下文
	ctx := context.Background()
	ctx = context.WithValue(ctx, "trace_id", "trace-123")
	ctx = context.WithValue(ctx, "span_id", "span-456")
	
	contextLogger := logger.WithContext(ctx)
	contextLogger.Info("traced message")
	
	output := buf.String()
	if !strings.Contains(output, "[trace:trace-123]") {
		t.Errorf("Output should contain trace ID, got: %s", output)
	}
}

// TestLoggerJSONFormat 测试JSON格式日志
func TestLoggerJSONFormat(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: JSONFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	logger.Info("json test", String("key", "value"))
	
	output := strings.TrimSpace(buf.String())
	
	// 验证是否为有效JSON
	var entry LogEntry
	err := json.Unmarshal([]byte(output), &entry)
	if err != nil {
		t.Errorf("Output should be valid JSON: %v", err)
	}
	
	if entry.Level != InfoLevel {
		t.Errorf("Expected level %v, got %v", InfoLevel, entry.Level)
	}
	if entry.Message != "json test" {
		t.Errorf("Expected message 'json test', got %q", entry.Message)
	}
	if entry.Fields["key"] != "value" {
		t.Errorf("Expected field value 'value', got %v", entry.Fields["key"])
	}
}

// TestLoggerLevelFiltering 测试日志级别过滤
func TestLoggerLevelFiltering(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  WarnLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 这些日志应该被过滤掉
	logger.Debug("debug message")
	logger.Info("info message")
	
	// 这些日志应该被记录
	logger.Warn("warn message")
	logger.Error("error message")
	
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	// 应该只有2行日志（warn和error）
	if len(lines) != 2 {
		t.Errorf("Expected 2 log lines, got %d", len(lines))
	}
	
	if !strings.Contains(lines[0], "[WARN]") {
		t.Errorf("First line should be WARN level, got: %s", lines[0])
	}
	if !strings.Contains(lines[1], "[ERROR]") {
		t.Errorf("Second line should be ERROR level, got: %s", lines[1])
	}
}

// TestLoggerWithField 测试WithField方法
func TestLoggerWithField(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 创建带字段的新logger
	fieldLogger := logger.WithField("component", "test")
	fieldLogger.Info("test message")
	
	output := buf.String()
	if !strings.Contains(output, "component=test") {
		t.Errorf("Output should contain field, got: %s", output)
	}
	
	// 验证原logger没有被修改
	buf.Reset()
	logger.Info("original message")
	output = buf.String()
	if strings.Contains(output, "component=test") {
		t.Errorf("Original logger should not have the field, got: %s", output)
	}
}

// TestLoggerWithFields 测试WithFields方法
func TestLoggerWithFieldsLogging(t *testing.T) {
    buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	fields := map[string]interface{}{
		"component": "test",
		"version":   "1.0",
		"debug":     true,
	}
	
	fieldLogger := logger.WithFields(fields)
	fieldLogger.Info("test message")
	
	output := buf.String()
	for key, value := range fields {
		expected := fmt.Sprintf("%s=%v", key, value)
		if !strings.Contains(output, expected) {
			t.Errorf("Output should contain %s, got: %s", expected, output)
		}
	}
}

// TestLoggerSetLevel 测试设置日志级别
func TestLoggerSetLevel(t *testing.T) {
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: os.Stdout,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	if logger.GetLevel() != InfoLevel {
		t.Errorf("Expected initial level %v, got %v", InfoLevel, logger.GetLevel())
	}
	
	logger.SetLevel(DebugLevel)
	if logger.GetLevel() != DebugLevel {
		t.Errorf("Expected level %v after SetLevel, got %v", DebugLevel, logger.GetLevel())
	}
}

// TestLoggerFormatted 测试格式化日志方法
func TestLoggerFormatted(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  DebugLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	// 测试格式化方法
	logger.Debugf("debug: %s = %d", "count", 42)
	logger.Infof("info: %s = %d", "count", 42)
	logger.Warnf("warn: %s = %d", "count", 42)
	logger.Errorf("error: %s = %d", "count", 42)
	
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	if len(lines) != 4 {
		t.Errorf("Expected 4 log lines, got %d", len(lines))
	}
	
	for _, line := range lines {
		if !strings.Contains(line, "count = 42") {
			t.Errorf("Line should contain formatted message, got: %s", line)
		}
	}
}

// TestLoggerFileOutput 测试文件输出
func TestLoggerFileOutput(t *testing.T) {
	tempDir := t.TempDir()
	logFile := filepath.Join(tempDir, "test.log")
	
	config := &Config{
		Level:  InfoLevel,
		Format: TextFormat,
		Output: logFile,
		Caller: false,
	}
	
	logger, err := NewLogger(config)
	if err != nil {
		t.Fatalf("Failed to create file logger: %v", err)
	}
	
	logger.Info("test file output")
	
	// 关闭logger以确保数据被写入
	err = logger.Close()
	if err != nil {
		t.Errorf("Failed to close logger: %v", err)
	}
	
	// 验证文件内容
	content, err := os.ReadFile(logFile)
	if err != nil {
		t.Fatalf("Failed to read log file: %v", err)
	}
	
	if !strings.Contains(string(content), "test file output") {
		t.Errorf("Log file should contain test message, got: %s", string(content))
	}
}

// TestGlobalLogger 测试全局日志记录器
func TestGlobalLogger(t *testing.T) {
	// 保存原始全局logger
	originalLogger := GetGlobalLogger()
	defer SetGlobalLogger(originalLogger)
	
	// 创建测试logger
	buf := &bytes.Buffer{}
	testLogger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	SetGlobalLogger(testLogger)
	
	// 测试全局函数
	Info("global info")
	Warn("global warn")
	Error("global error")
	
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	if len(lines) != 3 {
		t.Errorf("Expected 3 log lines, got %d", len(lines))
	}
	
	expectedMessages := []string{"global info", "global warn", "global error"}
	for i, line := range lines {
		if !strings.Contains(line, expectedMessages[i]) {
			t.Errorf("Line %d should contain %q, got: %s", i, expectedMessages[i], line)
		}
	}
}

// TestGlobalLoggerFormatted 测试全局格式化日志
func TestGlobalLoggerFormatted(t *testing.T) {
	// 保存原始全局logger
	originalLogger := GetGlobalLogger()
	defer SetGlobalLogger(originalLogger)
	
	// 创建测试logger
	buf := &bytes.Buffer{}
	testLogger := &KWDBLogger{
		level:  DebugLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	SetGlobalLogger(testLogger)
	
	// 测试全局格式化函数
	Debugf("debug: %d", 1)
	Infof("info: %d", 2)
	Warnf("warn: %d", 3)
	Errorf("error: %d", 4)
	
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	if len(lines) != 4 {
		t.Errorf("Expected 4 log lines, got %d", len(lines))
	}
	
	for i, line := range lines {
		expected := fmt.Sprintf(": %d", i+1)
		if !strings.Contains(line, expected) {
			t.Errorf("Line %d should contain %q, got: %s", i, expected, line)
		}
	}
}

// TestGlobalLoggerWithFields 测试全局字段日志
func TestGlobalLoggerWithFields(t *testing.T) {
	// 保存原始全局logger
	originalLogger := GetGlobalLogger()
	defer SetGlobalLogger(originalLogger)
	
	// 创建测试logger
	buf := &bytes.Buffer{}
	testLogger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	SetGlobalLogger(testLogger)
	
	// 测试全局字段函数
	WithField("component", "test").Info("with field")
	WithFields(map[string]interface{}{
		"key1": "value1",
		"key2": 42,
	}).Info("with fields")
	
	output := buf.String()
	if !strings.Contains(output, "component=test") {
		t.Errorf("Output should contain field, got: %s", output)
	}
	if !strings.Contains(output, "key1=value1") {
		t.Errorf("Output should contain key1, got: %s", output)
	}
	if !strings.Contains(output, "key2=42") {
		t.Errorf("Output should contain key2, got: %s", output)
	}
}

// TestLoggerConcurrency 测试并发日志记录
func TestLoggerConcurrency(t *testing.T) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	const numGoroutines = 10
	const messagesPerGoroutine = 10
	
	done := make(chan bool, numGoroutines)
	
	// 启动多个goroutine并发写日志
	for i := 0; i < numGoroutines; i++ {
		go func(id int) {
			for j := 0; j < messagesPerGoroutine; j++ {
				logger.Info(fmt.Sprintf("goroutine %d message %d", id, j))
			}
			done <- true
		}(i)
	}
	
	// 等待所有goroutine完成
	for i := 0; i < numGoroutines; i++ {
		<-done
	}
	
	// 验证日志数量
	output := buf.String()
	lines := strings.Split(strings.TrimSpace(output), "\n")
	
	expectedLines := numGoroutines * messagesPerGoroutine
	if len(lines) != expectedLines {
		t.Errorf("Expected %d log lines, got %d", expectedLines, len(lines))
	}
}

// BenchmarkLogger 日志记录性能测试
func BenchmarkLogger(b *testing.B) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	b.ResetTimer()
	
	b.Run("Info", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			logger.Info("benchmark message")
		}
	})
	
	b.Run("InfoWithFields", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			logger.Info("benchmark message", String("key", "value"), Int("count", i))
		}
	})
	
	b.Run("Infof", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			logger.Infof("benchmark message %d", i)
		}
	})
}

// BenchmarkLoggerJSON JSON格式日志性能测试
func BenchmarkLoggerJSON(b *testing.B) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: JSONFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		logger.Info("benchmark json message", String("key", "value"))
	}
}

// BenchmarkLoggerWithError 错误日志性能测试
func BenchmarkLoggerWithError(b *testing.B) {
	buf := &bytes.Buffer{}
	
	logger := &KWDBLogger{
		level:  InfoLevel,
		format: TextFormat,
		writer: buf,
		fields: make(map[string]interface{}),
		caller: false,
	}
	
    err := kwerrors.NewParseError("syntax error", 10, 5)
	
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		logger.WithError(err).Error("parse failed")
	}
}